#ifndef _LOG_HELPER_HPP
#define _LOG_HELPER_HPP

#include <stdint.h>
#include <sstream>
#include <iostream>

namespace LogWapper
{
	//#define Use_OutputDebugString
	#ifdef Use_OutputDebugString
		#include <windows.h>
	#elif defined(Use_QDebug)
		#include <QDebug>
	#endif


	enum LogLevel
	{
		kDisable	= -1,
		kDebug		= 0,
		kInfo		= 1,
		kWarn		= 2,
		kErr		= 3,
	};

	class LogHelper
	{
	public:
		LogHelper() 
		{
			_level = (int32_t)kDebug;
		}

		LogHelper(int32_t level, const char* func, uint32_t line)
			:_level(level), _funcName(func), _lineNo(line)
		{
		}

		inline LogHelper& operator<<(std::ostream& (*log)(std::ostream&))
		{
			_ss << log;
			return *this;
		}

		template <typename T>
		inline LogHelper& operator<<(const T& log) {
			if (_ss.str().length() > 0){
				_ss << " ";
			}
			_ss << log;
			return *this;
		}

		~LogHelper()
		{
			std::ostringstream oss;
			switch (_level)
			{
			case (int32_t)kDebug:
				oss << "[I] -";
				break;
			case (int32_t)kInfo:
				oss << "[D] -";
				break;
			case (int32_t)kWarn:
				oss << "[W] -";
				break;
			case (int32_t)kErr:
				oss << "[E] -";
				break;
			case (int32_t)kDisable:
				return;
			default:
				break;
			}

			oss << "[" << _funcName << ":" << _lineNo << "] - ";
			oss << _ss.str();
	#ifdef Use_OutputDebugString
			oss << std::endl;
			OutputDebugStringA(oss.str().c_str());
	#elif defined (Use_QDebug)
			qDebug() << oss.str().c_str();
	#else
			std::cout << oss.str() << std::endl;
	#endif

		}
	private:
		int32_t				_level;
		std::stringstream	_ss; 
		std::string			_funcName;
		uint32_t			_lineNo;
	};

	#define LOG(X)		LogHelper(X, __FUNCTION__, __LINE__)
};


#endif
